package uds_tb

import (
	"fmt"
	"server/apps/uds/uds_fld"
	"server/dbtools/xmysql"
	"server/global"
)


type UdsTb struct {
	global.BaseModel
	CreateFileType string `json:"createFileType" form:"createFileType" gorm:"column:createFileType;comment:创建文件方式;size:100;"`
	CreateFileName string `json:"createFileName" form:"createFileName" gorm:"column:createFileName;comment:创建文件名;size:100;"`
	Bsm            string `json:"bsm" form:"bsm" gorm:"column:bsm;comment:标识码;size:100;"`
	ColsString     string `json:"colsString" form:"colsString" gorm:"column:colsString;comment:字段名称字符串;size:1000;"`
	DbType        string `json:"dbType" form:"dbType" gorm:"column:dbType;comment:源数据库类型;size:100;"`
	UdsSchemaName string `json:"udsSchemaName" form:"udsSchemaName" gorm:"column:udsSchemaName;comment:uds模式名;size:50;"`
	UdsTbCategory string `json:"udsTbCategory" form:"udsTbCategory" gorm:"column:udsTbCategory;comment:表数据分类;size:50;"`
	UdsTbComment  string `json:"udsTbComment" form:"udsTbComment" gorm:"column:udsTbComment;comment:uds表注释;size:100;"`
	UdsTbLabel    string `json:"udsTbLabel" form:"udsTbLabel" gorm:"column:udsTbLabel;comment:uds表标签;size:50;"`
	UdsTbLen      *int   `json:"udsTbLen" form:"udsTbLen" gorm:"column:udsTbLen;comment:uds表长度;size:19;"`
	UdsTbName     string `json:"udsTbName" form:"udsTbName" gorm:"not null;column:udsTbName;comment:uds表名;size:191;"`
	Remarks       string `json:"remarks" form:"remarks" gorm:"column:remarks;comment:备注;size:250;"`
	UniqueCol     string `json:"uniqueCol" form:"uniqueCol" gorm:"column:uniqueCol;comment:唯一值列;size:250;"`

	UdsFlds []uds_fld.UdsFld `json:"udsFlds" gorm:"-"`
}


func (UdsTb) TableName() string {
	return "uds_tb"
}

func (m *UdsTb) CreateUdsTb() error {
	var err error
	if m.ID <= 0 {
		return fmt.Errorf("UdsTb.ID 为0")
	}
	udsDb := global.UdsDB
	tbIsExist, err := xmysql.MysqlTbExist(udsDb, m.UdsTbName)
	if err != nil {
		return err
	}
	if tbIsExist == true {
		return fmt.Errorf("UdsTb表名%s已经存在", m.UdsTbName)
	}

	var sqlCreateTb = fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s`(\n", m.UdsTbName)
	var strColKey string
	for idx, oneFld := range m.UdsFlds {
		if oneFld.ColName == "" ||
			oneFld.ColDataType == "" ||
			oneFld.ColComment == "" {
			return fmt.Errorf("字段关键内容不能为空")
		}
		sqlCreateTb += fmt.Sprintf("`%s` %s", oneFld.ColName, oneFld.ColDataType)

		if oneFld.ColCharSet != "" {
			sqlCreateTb += fmt.Sprintf(" CHARACTER SET %s", oneFld.ColCharSet)
		}
		if oneFld.ColComment != "" {
			sqlCreateTb += fmt.Sprintf(" COMMENT '%s'", oneFld.ColComment)
		}
		if oneFld.ColKey == true {
			if strColKey == "" {
				strColKey += fmt.Sprintf("`%s`", oneFld.ColName)
			} else {
				strColKey += fmt.Sprintf(", `%s`", oneFld.ColName)
			}
		}
		if idx < (len(m.UdsFlds) - 1) {
			sqlCreateTb += ",\n"
		}
	}
	if strColKey != "" {
		sqlCreateTb += fmt.Sprintf(",\nPRIMARY KEY (%s)\n", strColKey)
	}
	sqlCreateTb += fmt.Sprintf(") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '%s' ROW_FORMAT = DYNAMIC;", m.UdsTbComment)
	fmt.Printf("创建UDS表sql：\n%s\n", sqlCreateTb)

	_, err = udsDb.Exec(sqlCreateTb)
	if err != nil {
		fmt.Printf("创建UDS表失败：\nsql:%s\nerr:%v\n", sqlCreateTb, err)
		msg := fmt.Sprintf("创建ODS表失败：%s", err.Error())
		global.Logger.Error(msg)
		return err
	}

	return nil
}

func (m *UdsTb) UpdateFlds() error {
	var err error
	if m.ID <= 0 {
		return fmt.Errorf("UdsTb.ID 为0")
	}
	if m.UdsTbName == "" {
		return fmt.Errorf("UdsTb表名为空")
	}

	sqlDb := global.UdsDB
	if sqlDb == nil {
		return fmt.Errorf("UdsDB为nil")
	}

	tbIsExist, err := xmysql.MysqlTbExist(sqlDb, m.UdsTbName)
	if err != nil {
		msg := fmt.Sprintf("UDS检查表是否存在错误,err:%v", err)
		global.Logger.Error(msg)
		return fmt.Errorf(msg)
	}
	if tbIsExist == false {
		msg := fmt.Sprintf("UDS表不存在:%v", tbIsExist)
		global.Logger.Error(msg)
		return fmt.Errorf(msg)
	}

	var idList []uint
	for idx, oneFld := range m.UdsFlds {
		if oneFld.ColName == "" ||
			oneFld.ColDataType == "" ||
			oneFld.ColComment == "" {
			return fmt.Errorf("字段关键内容不能为空")
		}

		if oneFld.ID <= 0 {
			sqlAdd := fmt.Sprintf("ALTER TABLE %s ADD %s %s COMMENT '%s'", m.UdsTbName, oneFld.ColName, oneFld.ColDataType, oneFld.ColComment)
			_, err = sqlDb.Exec(sqlAdd)
			if err != nil {
				msg := fmt.Sprintf("UDS表增加列失败,sql:%s  err:%v", sqlAdd, err)
				global.Logger.Error(msg)
				return fmt.Errorf(msg)
			}
			oneFld.UdsTbId = m.ID
			err := oneFld.Create()
			if err != nil {
				msg := fmt.Sprintf("UDS表增加fld失败,err:%v", err)
				global.Logger.Error(msg)
				return fmt.Errorf(msg)
			}
			m.UdsFlds[idx] = oneFld
		} else {
			oldFld, err := udsFldService.GetUdsFldById(oneFld.ID)
			if err != nil {
				msg := fmt.Sprintf("UDS表获取原列定义失败:%v", err)
				global.Logger.Error(msg)
				return fmt.Errorf(msg)
			}
			if oldFld.ColName != oneFld.ColName {
				sqlChange := fmt.Sprintf("ALTER TABLE %s CHANGE %s %s %s", m.UdsTbName, oldFld.ColName, oneFld.ColName, oneFld.ColDataType)
				_, err = sqlDb.Exec(sqlChange)
				if err != nil {
					msg := fmt.Sprintf("UDS表修改列名失败,sql:%s,err:%v", sqlChange, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}
			if oldFld.ColDataType != oneFld.ColDataType {
				sqlModify := fmt.Sprintf("ALTER TABLE %s MODIFY %s %s", m.UdsTbName, oneFld.ColName, oneFld.ColDataType)
				_, err = sqlDb.Exec(sqlModify)
				if err != nil {
					msg := fmt.Sprintf("UDS表增加列失败,sql:%s,err:%v", sqlModify, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}
			if oldFld.ColKey == false && oneFld.ColKey == true {
				sqlPRI := fmt.Sprintf("ALTER TABLE %s ADD PRIMARY KEY (%s)", m.UdsTbName, oneFld.ColName)
				_, err = sqlDb.Exec(sqlPRI)
				if err != nil {
					msg := fmt.Sprintf("UDS表增加主键失败,sql:%s,err:%v", sqlPRI, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
				oldFld.NotNull = true
			}
			if oldFld.ColKey == true && oneFld.ColKey == false {
				if oldFld.AutoIncrement == true {
					sqlModify := fmt.Sprintf("ALTER TABLE %s MODIFY %s %s", m.UdsTbName, oneFld.ColName, oneFld.ColDataType)
					_, err = sqlDb.Exec(sqlModify)
					if err != nil {
						msg := fmt.Sprintf("UDS表删除自增失败,sql:%s,err:%v", sqlModify, err)
						global.Logger.Error(msg)
						return fmt.Errorf(msg)
					}
				}
				sqlPRI := fmt.Sprintf("ALTER TABLE %s DROP PRIMARY KEY", m.UdsTbName)
				_, err = sqlDb.Exec(sqlPRI)
				if err != nil {
					msg := fmt.Sprintf("UDS表删除主键失败,sql:%s,err:%v", sqlPRI, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}

			if oldFld.Unique == false && oneFld.Unique == true {
				sqlUnique := fmt.Sprintf("ALTER TABLE %s ADD UNIQUE (%s)", m.UdsTbName, oneFld.ColName)
				_, err = sqlDb.Exec(sqlUnique)
				if err != nil {
					msg := fmt.Sprintf("UDS表增加唯一列失败,sql:%s,err:%v", sqlUnique, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}
			if oldFld.Unique == true && oneFld.Unique == false {
				sqlDropUnique := fmt.Sprintf("ALTER TABLE %s DROP INDEX %s", m.UdsTbName, oneFld.ColName)
				_, err = sqlDb.Exec(sqlDropUnique)
				if err != nil {
					msg := fmt.Sprintf("UDS表删除唯一列失败,sql:%s,err:%v", sqlDropUnique, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}

			if oldFld.NotNull == false && oneFld.NotNull == true {
				sqlNodNull := fmt.Sprintf("ALTER TABLE %s MODIFY %s %s NOT NULL", m.UdsTbName, oneFld.ColName, oneFld.ColDataType)
				_, err = sqlDb.Exec(sqlNodNull)
				if err != nil {
					msg := fmt.Sprintf("UDS表设置%s 必填(NotNull)失败,sql:%s,err:%v", oneFld.ColName, sqlNodNull, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}
			if oldFld.NotNull == true && oneFld.NotNull == false {
				if oneFld.ColKey == true {
					msg := fmt.Sprintf("主键(%s)必填,不能为空", oneFld.ColName)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
				sqlNodNull := fmt.Sprintf("ALTER TABLE %s MODIFY %s %s NULL", m.UdsTbName, oneFld.ColName, oneFld.ColDataType)
				_, err = sqlDb.Exec(sqlNodNull)
				if err != nil {
					msg := fmt.Sprintf("UDS表置%s 必填(NotNull)失败,sql:%s,err:%v", oneFld.ColName, sqlNodNull, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}

			if oldFld.AutoIncrement == false && oneFld.AutoIncrement == true {
				if oneFld.ColKey == false {
					msg := fmt.Sprintf("自增列(%s)必须为主键,请设置", oneFld.ColName)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
				sqlAutoIncrement := fmt.Sprintf("ALTER TABLE %s MODIFY %s %s auto_increment", m.UdsTbName, oneFld.ColName, oneFld.ColDataType)
				_, err = sqlDb.Exec(sqlAutoIncrement)
				if err != nil {
					msg := fmt.Sprintf("UDS表设置%s 自增(AutoIncrement)失败,sql:%s,err:%v", oneFld.ColName, sqlAutoIncrement, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}
			if oldFld.AutoIncrement == true && oneFld.AutoIncrement == false {
				delDataType := oneFld.ColDataType
				if oneFld.NotNull == true {
					delDataType += " NOT NULL"
				}
				sqlAutoIncrement := fmt.Sprintf("ALTER TABLE %s MODIFY %s %s", m.UdsTbName, oneFld.ColName, delDataType)
				_, err = sqlDb.Exec(sqlAutoIncrement)
				if err != nil {
					msg := fmt.Sprintf("UDS表置%s 自增(AutoIncrement)失败,sql:%s,err:%v", oneFld.ColName, sqlAutoIncrement, err)
					global.Logger.Error(msg)
					return fmt.Errorf(msg)
				}
			}

			err = oneFld.Update()
			if err != nil {
				return err
			}
			if err != nil {
				msg := fmt.Sprintf("UDS表更新fld失败,err:%v", err)
				global.Logger.Error(msg)
				return fmt.Errorf(msg)
			}
		}
		idList = append(idList, oneFld.ID)
	}
	var delFlds []uds_fld.UdsFld
	err = global.SysDB.Where("id not in ?", idList).Find(&delFlds).Error
	if err != nil {
		msg := fmt.Sprintf("UDS查找需删除fld失败,err:%v", err)
		global.Logger.Error(msg)
		return fmt.Errorf(msg)
	}
	for _, oneDelFld := range delFlds {
		sqlDrop := fmt.Sprintf("ALTER TABLE %s Drop %s", m.UdsTbName, oneDelFld.ColName)
		_, err = sqlDb.Exec(sqlDrop)
		if err != nil {
			msg := fmt.Sprintf("UDS表删除物理表列失败,sql:%s,err:%v", sqlDrop, err)
			global.Logger.Error(msg)
			return fmt.Errorf(msg)
		}
		err = udsFldService.DeleteUdsFld(oneDelFld)
		if err != nil {
			msg := fmt.Sprintf("UDS表删udsFld失败,err:%v", err)
			global.Logger.Error(msg)
			return fmt.Errorf(msg)
		}
	}
	return nil
}
